#! /bin/bash

# Print usage info
function usage {
   echo ""
   echo "This script is intended to install WinXP virtual machines from a template on XenServer hypervisor."
   echo ""
   echo "The script must be used in conjunction with a VB script named 'HostRenamer.vbs' which must be copied into"
   echo "VM's Group Policy startup directory, i.e. 'C:\\WINDOWS\\System32\\GroupPolicy\\Machine\\Scripts\\Startup' and activated"
   echo "in accordance with http://support.microsoft.com/kb/307882 document by adding a _startup_ record into"
   echo "'Local Computer Policy -> Computer Configuration -> Windows Settings -> Scripts'. The VB script will be activated"
   echo "on each reboot/startup and will update (if necessary) the VM's hostname to match VM's name on XenServer hypervisor." 
   echo "Once the hostname is updated the VM is shutdowned automatically and waits for all remaining VMs to be instantiated."
   echo "Finally, all successfully installed VMs are started."
   echo ""
   echo "Usage: $0 [options]"
   echo ""
   echo "Options:"
   echo ""
   echo "   --help                     This help message."
   echo "   --start=<number>           Numerical suffix of the _first_ VM to be created (default 1)"
   echo "   --stop=<number>            Numerical suffix of the _last_ VM to be created (default 1)"
   echo "   --prefix=<text>            Prefix for ALL VMs (default WXP)"
   echo "   --template=<text>          Template to be used to create VMs (default WinXP)"
   echo "   --format=<text>            Printf like format string to compile VMs' names (default '%s%02d')"
   echo ""
   echo "\n"
}

# Initialization
shopt -s extglob
LOGFILE=/dev/null                                                 # Default log filename
if ((1)); then
   LOGFILE=$(date +"%y%m%d_%H%M%S").log                           # When ((1)) is used, $LOGFILE will be created on failed installation
fi
PROMPT=">> "                                                      # Prompt to be displayed while interacting with user
TEMPLATE="WinXP"                                                  # Template to be used for all VMs
PREFIX="WXP"                                                      # Hostname prefix for each VM
SYMBS=( '-' '\' '|' '/' )                                         # Array of characters to show progress animation
SPACES=""; for ((i=0;i<20;i++)); do SPACES=" $SPACES"; done;      # A string with 20 spaces
FORMAT="%s%02d"

# Parse command line options
for opt in $@
do
   case $opt in
      --help*)
         printf "$(usage)\n"
         exit 0
         ;;
      --start=*)
         STARTIDX=$(echo $opt | sed 's/[-a-zA-Z0-9]*=//')
			[ -z $STOPIDX ] && STOPIDX=$STARTIDX
         ;;
      --stop=*)
         STOPIDX=$(echo $opt | sed 's/[-a-zA-Z0-9]*=//')
			[ -z $STARTIDX ] && STARTIDX=$STOPIDX
         ;;
      --template=*)
         TEMPLATE=$(echo $opt | sed 's/[-a-zA-Z0-9]*=//')
         ;;
      --prefix=*)
         PREFIX=$(echo $opt | sed 's/[-a-zA-Z0-9]*=//')
         ;;
      --format=*)
         FORMAT=$(echo $opt | sed 's/[-a-zA-Z0-9]*=//')
         ;;
      *)
         echo "Unrecognized command-line option '$opt'." 1>&2
         printf "$(usage)\n"
         exit 1
         ;;
   esac
done
[ -z $STOPIDX -a -z $STARTIDX ] && (STOPIDX=1; STARTIDX=1)

# Error handling
if [[ $STARTIDX != ?(+)+([0-9]) ]]; then
   echo "Start index (--start=...) must be non-negative" 1>&2
   exit 3
fi
if [[ $STOPIDX -lt $STARTIDX ]]; then
   echo "Stop index (--stop=...) must be _not_less_ that start index (--start=...)" 1>&2
   exit 3
fi
if [ -z $(xe template-list name-label=$TEMPLATE --minimal) ]; then
   echo "Specified template '$TEMPLATE' does not exist." 1>&2
   exit 4
fi
# Evaluate number of VMs to be installed
((NUMVMS=STOPIDX-STARTIDX+1))
# Start the process...
echo "$NUMVMS VM(s) with template '$TEMPLATE' are about to be installed."
# Main loop
for ((i=0;i<$NUMVMS;i++)); do
   name=$(printf $FORMAT $PREFIX $((STARTIDX+i)))
   printf "\r%s: installing VM from the template...%s\r" "$name" "$SPACES"
   vm=$(xe vm-install new-name-label="$name" template="$TEMPLATE" 2>> "$LOGFILE")
   if [ -z $vm ]; then
      printf "\r%s: installation failed.%s\n" "$name" "$SPACES"
      break
   fi
   logPrefix=$(printf "%s (%s)" "$name" "$vm")
   printf "\r%s: starting up the VM...%s\r" "$logPrefix" "$SPACES"
   xe vm-start uuid=$vm 2>> "$LOGFILE"
   if [ $? -ne 0 ]; then
      printf "\r%s: installation failed.%s\n" "$logPrefix" "$SPACES"
      break
   fi
   for ((j=0;;j=($j+1)%${#SYMBS[@]})); do
      ((($j % 10) == 0)) && [ $(xe vm-list power-state=halted uuid=$vm --minimal) ] && break
      printf "\r%s: waiting for VM to halt... %s%s\r" "$logPrefix" "${SYMBS[j]}" "$SPACES"
      sleep 0.5
   done
   printf "\r%s: has been installed%s\n" "$logPrefix" "$SPACES"
   VMs[$i]=$vm
done
echo "Starting up installed VM(s)..."
i=0
for vm in ${VMs[@]}; do
   xe vm-start uuid=$vm 2>> "$LOGFILE" && ((i++))
done
[ $i -gt 0 ] && echo "$i VM(s) have been installed and started."



